package com.gitee.qdbp.general.marketing.biz.activity.basic;

import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.jdbc.ordering.OrderPaging;
import com.gitee.qdbp.able.jdbc.paging.PageList;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.enums.DataState;
import com.gitee.qdbp.base.model.condition.OrderWhere;
import com.gitee.qdbp.base.model.condition.Where;
import com.gitee.qdbp.general.common.api.sequence.service.ILocalSequenceGenerator;
import com.gitee.qdbp.general.marketing.api.activity.model.AwardCoreBean;
import com.gitee.qdbp.general.marketing.api.activity.model.AwardCoreUpdate;
import com.gitee.qdbp.general.marketing.api.activity.model.AwardCoreWhere;
import com.gitee.qdbp.general.marketing.biz.activity.dao.IAwardCoreBasicDao;
import com.gitee.qdbp.tools.utils.DateTools;
import com.gitee.qdbp.tools.utils.JsonTools;
import com.gitee.qdbp.tools.utils.VerifyTools;

/**
 * 奖品主基础业务类
 *
 * @author zhh
 * @version 181114
 */
@Service
public class AwardCoreBasic {

    /** 日志对象 **/
    private static final Logger log = LoggerFactory.getLogger(AwardCoreBasic.class);

    /** 序列号生成(ID) **/
    @Autowired
    private ILocalSequenceGenerator sequenceGenerator;

    /** 奖品主DAO **/
    @Autowired
    private IAwardCoreBasicDao awardCoreBasicDao;

    /**
     * 奖品主查询
     *
     * @param where 查询条件
     * @return 奖品主
     * @throws ServiceException 查询失败
     */
    public AwardCoreBean find(AwardCoreWhere where) throws ServiceException {
        String msg = "Failed to query AwardCore. ";

        if (where == null) {
            log.error(msg + "params is null: where");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (where.getDataState() == null) {
            where.setDataState(DataState.NORMAL);
        }

        doHandleDate(where);

        AwardCoreBean bean;
        try {
            bean = awardCoreBasicDao.find(Where.of(where));
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + "\n\t" + JsonTools.toJsonString(where), e);
            throw new ServiceException(ResultCode.DB_SELECT_ERROR, e);
        }

        if (bean == null) {
            log.trace("AwardCore not found. {}", JsonTools.toJsonString(where));
        }
        return bean;
    }

    /**
     * 根据奖品编号查询奖品主
     *
     * @param id 奖品编号
     * @return 奖品主
     * @throws ServiceException 查询失败
     */
    public AwardCoreBean findById(String id) throws ServiceException {
        String msg = "Failed to query AwardCore by id. ";

        if (VerifyTools.isBlank(id)) {
            log.error(msg + "params is null: id");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        AwardCoreWhere where = new AwardCoreWhere();
        where.setId(id);

        return find(where);
    }

    /**
     * 奖品主查询
     *
     * @param paging 排序分页条件
     * @return 奖品主列表
     * @throws ServiceException 查询失败
     */
    public PageList<AwardCoreBean> list(OrderPaging paging) throws ServiceException {
        String msg = "Failed to query AwardCore. ";

        if (paging == null) {
            log.error(msg + "params is null: paging");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        return list(new AwardCoreWhere(), paging);
    }

    /**
     * 奖品主查询
     *
     * @param where 查询条件
     * @param paging 排序分页条件
     * @return 奖品主列表
     * @throws ServiceException 查询失败
     */
    public PageList<AwardCoreBean> list(AwardCoreWhere where, OrderPaging paging) throws ServiceException {
        String msg = "Failed to query AwardCore. ";

        if (paging == null) {
            log.error(msg + "params is null: paging");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (where == null) {
            where = new AwardCoreWhere();
            where.setDataState(DataState.NORMAL);
        } else if (where.getDataState() == null) {
            where.setDataState(DataState.NORMAL);
        }

        doHandleDate(where);

        try {
            OrderWhere<AwardCoreWhere> ow = OrderWhere.of(where, paging.getOrderings());
            return PageList.of(awardCoreBasicDao.list(ow, paging));
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + "\n\t" + JsonTools.toJsonString(where), e);
            throw new ServiceException(ResultCode.DB_SELECT_ERROR, e);
        }
    }

    /**
     * 根据奖品编号查询奖品主列表
     *
     * @param ids 奖品编号列表
     * @return 奖品主列表
     * @throws ServiceException 查询失败
     */
    public PageList<AwardCoreBean> listByIds(List<String> ids) throws ServiceException {
        String msg = "Failed to query AwardCore by id list. ";

        if (VerifyTools.isBlank(ids)) {
            log.error(msg + "params is null: ids");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        AwardCoreWhere where = new AwardCoreWhere();
        where.setIds(ids);

        return list(where, OrderPaging.NONE);
    }

    /**
     * 创建奖品主
     *
     * @param model 待新增的奖品主
     * @return 受影响行数
     * @throws ServiceException 创建失败
     */
    public int create(AwardCoreBean model) throws ServiceException {
        String msg = "Failed to create AwardCore. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (VerifyTools.isBlank(model.getId())) {
            model.setId(sequenceGenerator.generate(AwardCoreBean.TABLE));
        }
        model.setDataState(DataState.NORMAL);

        doHandleDate(model);

        // 向aty_award_core表插入记录
        int rows;
        try {
            rows = awardCoreBasicDao.insert(model);
        } catch (DuplicateKeyException e) {
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(model), e);
            throw new ServiceException(ResultCode.DB_DUPLICATE_KEY, e);
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(model), e);
            throw new ServiceException(ResultCode.DB_INSERT_ERROR, e);
        }

        if (rows == 0) {
            log.error(msg + "affected rows is 0. \n\t" + JsonTools.toJsonString(model));
            throw new ServiceException(ResultCode.DB_INSERT_ERROR);
        }
        return rows;
    }

    /**
     * 批量创建奖品主
     *
     * @param models 待新增的奖品主
     * @return 受影响行数
     * @throws ServiceException 创建失败
     */
    public int create(List<AwardCoreBean> models) throws ServiceException {
        String msg = "Failed to batch create AwardCore. ";

        if (VerifyTools.isBlank(models)) {
            log.error(msg + "params is null: models");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        for (AwardCoreBean model : models) {
            if (VerifyTools.isBlank(model.getId())) {
                model.setId(sequenceGenerator.generate(AwardCoreBean.TABLE));
            }
            model.setDataState(DataState.NORMAL);

            doHandleDate(model);
        }

        // 向aty_award_core表插入记录
        int rows;
        try {
            rows = awardCoreBasicDao.inserts(models);
        } catch (DuplicateKeyException e) {
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(models), e);
            throw new ServiceException(ResultCode.DB_DUPLICATE_KEY, e);
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(models), e);
            throw new ServiceException(ResultCode.DB_INSERT_ERROR, e);
        }

        int size = models.size();
        if (rows != size) {
            String desc = size > 0 ? "affected rows " + rows + "!=" + size + ". " : "affected rows is 0. ";
            log.error(msg + desc + "\n\t" + JsonTools.toJsonString(models));
            throw new ServiceException(ResultCode.DB_INSERT_ERROR);
        }
        return rows;
    }

    /**
     * 修改奖品主
     *
     * @param model 待修改的内容
     * @param errorOnUnaffected 受影响行数为0时是否抛异常
     * @return 受影响行数
     * @throws ServiceException 修改失败
     */
    public int update(AwardCoreUpdate model, boolean errorOnUnaffected) throws ServiceException {
        String msg = "Failed to update AwardCore. ";

        if (model == null) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (model.getWhere() == null) {
            if (VerifyTools.isNotBlank(model.getId())) {
                model.getWhere(true).setId(model.getId());
            }
        }
        model.setDataState(null); // 数据状态只允许通过删除操作来修改
        AwardCoreWhere where = model.getWhere(true);
        if (where.getDataState() == null) {
            where.setDataState(DataState.NORMAL);
        }

        return doUpdate(model, 0, errorOnUnaffected);
    }

    /**
     * 根据奖品编号删除奖品主
     *
     * @param ids 待删除的奖品主的奖品编号
     * @param errorOnRowsNotMatch 删除行数不匹配时是否抛异常
     * @return 删除行数
     * @throws ServiceException 删除失败
     */
    public int deleteByIds(List<String> ids, boolean errorOnRowsNotMatch) throws ServiceException {
        String msg = "Failed to delete AwardCore. ";

        if (VerifyTools.isBlank(ids)) {
            log.error(msg + "params is null: ids");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        AwardCoreWhere where = new AwardCoreWhere();
        where.setIds(ids);

        return doDelete(where, ids.size(), errorOnRowsNotMatch);
    }

    /**
     * 根据条件删除奖品主
     *
     * @param where 条件
     * @param errorOnUnaffected 删除行数为0时是否抛异常
     * @return 删除行数
     * @throws ServiceException 删除失败
     */
    public int delete(AwardCoreWhere where, boolean errorOnUnaffected) throws ServiceException {
        String msg = "Failed to delete AwardCore. ";

        if (where == null) {
            log.error(msg + "params is null: where");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        return doDelete(where, 0, errorOnUnaffected);
    }

    /**
     * 根据条件删除奖品主
     *
     * @param where 条件
     * @param size 应删除条数, 0表示未知
     * @param errorOnRowsNotMatch 删除行数不匹配时是否抛异常
     * @param isId 是不是唯一主键
     * @return 删除行数
     * @throws ServiceException 删除失败
     */
    private int doDelete(AwardCoreWhere where, int size, boolean errorOnRowsNotMatch) throws ServiceException {
        // 逻辑删除
        if (where.getDataState() == null) {
            where.setDataState(DataState.NORMAL);
        }
        AwardCoreUpdate model = new AwardCoreUpdate();
        model.setDataState(DataState.DELETED);
        model.setWhere(where);
        return doUpdate(model, size, errorOnRowsNotMatch);
    }

    /**
     * 修改奖品主
     *
     * @param model 待修改的内容
     * @param size 应删除条数, 0表示未知
     * @param errorOnRowsNotMatch 删除行数不匹配时是否抛异常
     * @return 受影响行数
     * @throws ServiceException 修改失败
     */
    private int doUpdate(AwardCoreUpdate model, int size, boolean errorOnRowsNotMatch) throws ServiceException {
        String msg = "Failed to update AwardCore. ";

        if (model == null) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (model.getWhere() == null) {
            log.error(msg + "params is null: model.getWhere()");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        doHandleDate(model);
        doHandleDate(model.getWhere());

        int rows;
        try {
            rows = awardCoreBasicDao.update(model);
        } catch (DuplicateKeyException e) {
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(model), e);
            throw new ServiceException(ResultCode.DB_DUPLICATE_KEY, e);
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(model), e);
            throw new ServiceException(ResultCode.DB_UPDATE_ERROR, e);
        }

        if (size > 0 && rows != size || rows == 0) {
            String desc = size > 0 ? "affected rows != " + size + ". " : "affected rows is 0. ";
            if (errorOnRowsNotMatch) {
                log.error(msg + desc + "\n\t" + JsonTools.toJsonString(model));
                throw new ServiceException(ResultCode.DB_UPDATE_ERROR);
            } else {
                log.debug(msg + desc + "\n\t" + JsonTools.toJsonString(model));
            }
        }
        return rows;
    }

    // 由于数据库不支持毫秒, 超过500毫秒会因四舍五入导致变成下一天0点, 因此将毫秒清掉
    protected static void doHandleDate(AwardCoreBean model) {
        if (model == null) {
            return;
        }

        if (VerifyTools.isNotBlank(model.getCreateTime())) { // 创建时间
            model.setCreateTime(DateTools.setMillisecond(model.getCreateTime(), 0));
        }
    }

    // 由于数据库不支持毫秒, 超过500毫秒会因四舍五入导致变成下一天0点, 因此将毫秒清掉
    // 处理XxxTime, XxxTimeMin和XxxTimeMax, XxxTimeMinWithDay和XxxTimeMaxWithDay
    protected static void doHandleDate(AwardCoreWhere model) {
        if (model == null) {
            return;
        }

        if (VerifyTools.isNotBlank(model.getCreateTime())) { // 创建时间
            model.setCreateTime(DateTools.setMillisecond(model.getCreateTime(), 0));
        }

        if (VerifyTools.isNotBlank(model.getCreateTimeMin())) { // 最小创建时间
            model.setCreateTimeMin(DateTools.setMillisecond(model.getCreateTimeMin(), 0));
        }
        if (VerifyTools.isNotBlank(model.getCreateTimeMinWithDay())) { // 最小创建时间
            model.setCreateTimeMinWithDay(DateTools.toStartTime(model.getCreateTimeMinWithDay()));
        }
        if (VerifyTools.isNotBlank(model.getCreateTimeMax())) { // 最大创建时间
            model.setCreateTimeMax(DateTools.setMillisecond(model.getCreateTimeMax(), 0));
        }
        if (VerifyTools.isNotBlank(model.getCreateTimeMaxWithDay())) { // 最大创建时间
            model.setCreateTimeMaxWithDay(DateTools.setMillisecond(DateTools.toEndTime(model.getCreateTimeMaxWithDay()), 0));
        }
    }
}